#include "stdafx.h"
#include "ProjectEditorView.h"

#include "GlobalAppData.h"

// gfx
#include "Graphics.h"
#include "RenderingSystem.h"
#include "EditorRenderStage.h"
#include "DeferredPipeline.h"
#include "ModelNode.h"
#include "MeshInstance.h"
#include "Mesh.h"

// physics
#include "PhysicsSystem.h"

// math
#include "Ray.h"

// scene
#include "Camera.h"
#include "Scene.h"
#include "SceneLoader.h"
#include "SceneSaver.h"
#include "WorldData.h"
#include "NodeUtil.h"

// editor
#include "RenderSettingsGui.h"
#include "AddObjectGui.h"

// gui
#include "Window.h"
#include "EditObjectGui.h"

#include "EditObjectTwBar.h"
#include "AddObjectTwBar.h"
#include "RenderSettingsTwBar.h"


using namespace predit;

static TwBar * BarLoadObj;
static mscene::ModelNode * Object = NULL;
static mscene::Scene * Scene;
static mgfx::RenderingSystem * RenderSys;
static mphys::PhysicsSystem * PhysicsSys;

ProjectEditorView::ProjectEditorView()
	: mCameraStrafing(false), mCameraRotating(false), mEditMode(EDIT_NOT_SELECTED)
{
	mName = "EditorView View";
}

void ProjectEditorView::init( )
{
	View::load();

	

	RenderSys = mRenderSystem = new mgfx::RenderingSystem;
	PhysicsSys = mPhysicsSystem = new mphys::PhysicsSystem;

	Scene = new mscene::Scene(*mRenderSystem, *mPhysicsSystem);
	mscene::loadScene("scene.xml", makeWorldData(Scene, mRenderSystem, mPhysicsSystem));

	float screenAspect = (float)mcore::GlobalAppData::Instance.ScreenWidth / (float)mcore::GlobalAppData::Instance.ScreenHeight;
	mCamera = &Scene->getCamera();

	mCamera->walk(-50);
	mCamera->setLens(0.25f * PI, screenAspect, 5.0f, 15000.0f);
	mRenderSystem->setProjMatrix(mCamera->proj());

	initGui();
}

void ProjectEditorView::unload()
{
	mSeletectedNodes.clear();

	SAFE_DELETE(mRenderSettingsGui);

	SAFE_DELETE(Scene);

	SAFE_DELETE(mPhysicsSystem);
	SAFE_DELETE(mRenderSystem);

	View::unload();
}

void ProjectEditorView::update(float dt)
{ 
	Scene->update(dt);
	mRenderSystem->update(dt);
}

void ProjectEditorView::draw()
{
	mRenderSystem->setViewMatrix(mCamera->view());
	mRenderSystem->setEyePosition(mCamera->position());
	mRenderSystem->setViewFrustum(mCamera->Frustum_);
	mgfx::DeferredPipeline::get().render(mRenderSystem->Data, mRenderSystem->Settings);

	mgfx::EditorRenderData edRenderData;
	mscene::fillEditorRenderDataFromNodes(mSeletectedNodes, edRenderData);
	mgfx::renderEditorData(mRenderSystem->Data, edRenderData, mRenderSystem->Settings);

	mGui->draw();
}

bool ProjectEditorView::onWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
	if(sendInputToGUI(msg, wParam, lParam))
	{
		return true;
	}

	//if(mEditObjectGui->NodeRemoved || editObjectIsRemoved())
	//{
	//	mSeletectedNodes.clear();
	//	mEditMode = EDIT_NOT_SELECTED;
	//	mEditObjectGui->IsVisible = false;
	//	mAddObjectGui->GuiWindow->IsVisible = true;

	//	editObjectHideBar();
	//}

	if(medit::editObjectIsRemoved())
	{
		medit::hideEditObjectBar();
		mSeletectedNodes.clear();
		mEditMode = EDIT_NOT_SELECTED;
		//mEditObjectGui->IsVisible = false;
		//mAddObjectGui->GuiWindow->IsVisible = true;
	}

	switch( msg )
	{
	case WM_MOUSEMOVE:
		{
			static bool firstTime = true;
			int mousePosX = LOWORD(lParam);
			int mousePosY = HIWORD(lParam);
			if(firstTime)
			{
				firstTime = false;
			}
			else
			{
				int diffY = mPrevMousePosY - mousePosY;
				int diffX = mPrevMousePosX - mousePosX;
				if(diffY != 0 || diffX != 0)
				{
					if(mCameraStrafing)
					{
						mCamera->strafe(diffX * 0.6f);
						mCamera->moveVertically(-diffY * 0.6f);
					}
					else if(mCameraRotating)
					{
						mCamera->pitch(float(-diffY) * 0.003f);
						mCamera->rotateY(float(-diffX) * 0.003f);
					}
					//mScene->mouseMove(diffX, diffY);
				}

			}
			mPrevMousePosX = mousePosX;
			mPrevMousePosY = mousePosY;
			return true;
		}
		break;

	case WM_LBUTTONDOWN:

		break;

	case WM_LBUTTONUP:

		{

		}
		break;

	case WM_MBUTTONDOWN:
		mCameraStrafing = true;
		break;

	case WM_MBUTTONUP:
		mCameraStrafing = false;
		break;

	case WM_RBUTTONDOWN:
		mCameraRotating = true;
		break;

	case WM_RBUTTONUP:
		mCameraRotating = false;
		break;

	case WM_MOUSEWHEEL:
		{
			float delta = GET_WHEEL_DELTA_WPARAM(wParam);
			mCamera->walk(delta * 0.4f);
		}
		break;

	case WM_KEYDOWN:

		break;

	case WM_KEYUP:

		break;
	}
	return false;
}

static char ObjPath[128];

static void TW_CALL loadObject(void *clientData)
{
	Object = new mscene::ModelNode(*Scene, mscene::ModelNode::OTHER, "Object");

	Object->Position = XMFLOAT3(0, 0, 0);
	Object->Scale = XMFLOAT3(1.0f, 1.0f, 1.0f);
	XMStoreFloat4(&Object->Orientation, XMQuaternionRotationRollPitchYaw(0, 0, 0));

	mgfx::MeshInstance * mesh = RenderSys->createMeshInstance(ObjPath);
	mesh->Material_ = mesh->Mesh_->Materials[0];

	Object->setModel(*mesh);

	//Floor->setRigidBody(PhysSys.createSphereRigidBody());
	//Floor->IsStatic = true;
	//Floor->updateRigidBody();
	Scene->addNode(*Object);
}

void ProjectEditorView::initGui()
{
	mRenderSettingsGui = new medit::RenderSettingsGui(&mRenderSystem->Settings);
	mGui->addChild(*mRenderSettingsGui->GuiWindow);

	//mAddObjectGui = new medit::AddObjectGui(mscene::makeWorldData(mScene, mRenderSystem, mPhysicsSystem));
	//mGui->addChild(*mAddObjectGui->GuiWindow);

	medit::showRenderSettingsBar(mRenderSystem->Data, mRenderSystem->Settings);

	//mEditObjectGui = new medit::EditObjectGui(*mScene, *mCamera);
	//mGui->addChild(*mEditObjectGui);
	//mEditObjectGui->IsVisible = false;
	// 

	BarLoadObj = TwNewBar("Load object");
	
	TwAddVarRW(BarLoadObj, "Path", TW_TYPE_CSSTRING(128), ObjPath, "");
	TwAddButton(BarLoadObj, "Copy object", loadObject, NULL, "");
}
